package cn.hlife.com.bluetooth20_connect.lib;


import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Handler;
import android.os.Message;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;

import cn.hlife.com.bluetooth20_connect.util.LogUtils;

public class BluetoothService {
    private static final String TAG = "BluetoothService";
    private static final boolean D = true;
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_CONNECTION_LOST = 5;
    public static final int MESSAGE_UNABLE_CONNECT = 6;
    private static final String NAME = "BTPrinter";
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
    private final Handler mHandler;
    private BluetoothService.AcceptThread mAcceptThread;
    private BluetoothService.ConnectThread mConnectThread;
    private BluetoothService.ConnectedThread mConnectedThread;
    private int mState = 0;
    public static final int STATE_NONE = 0;
    public static final int STATE_LISTEN = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;

    public BluetoothService(Context context, Handler handler) {
        this.mHandler = handler;
    }

    public synchronized boolean isAvailable() {
        return this.mAdapter != null;
    }

    public synchronized boolean isBTopen() {
        return this.mAdapter.isEnabled();
    }

    public synchronized BluetoothDevice getDevByMac(String mac) {
        return this.mAdapter.getRemoteDevice(mac);
    }

    public synchronized BluetoothDevice getDevByName(String name) {
        BluetoothDevice tem_dev = null;
        Set pairedDevices = this.getPairedDev();
        if (pairedDevices.size() > 0) {
            Iterator var5 = pairedDevices.iterator();

            while (var5.hasNext()) {
                BluetoothDevice device = (BluetoothDevice) var5.next();
                if (device.getName().indexOf(name) != -1) {
                    tem_dev = device;
                    break;
                }
            }
        }

        return tem_dev;
    }

    public synchronized void sendMessage(String message, String charset) {
        if (message.length() > 0) {
            byte[] send;
            try {
                send = message.getBytes(charset);
            } catch (UnsupportedEncodingException var5) {
                send = message.getBytes();
            }

            this.write(send);
            byte[] tail = new byte[]{10, 13, 0};
            this.write(tail);
        }

    }

    public synchronized Set<BluetoothDevice> getPairedDev() {
        Set dev = null;
        dev = this.mAdapter.getBondedDevices();
        return dev;
    }

    public synchronized boolean cancelDiscovery() {
        return this.mAdapter.cancelDiscovery();
    }

    public synchronized boolean isDiscovering() {
        return this.mAdapter.isDiscovering();
    }

    public synchronized boolean startDiscovery() {
        return this.mAdapter.startDiscovery();
    }

    private synchronized void setState(int state) {
        this.mState = state;
        this.mHandler.obtainMessage(1, state, -1).sendToTarget();
    }

    public synchronized int getState() {
        return this.mState;
    }

    public synchronized void start() {
        LogUtils.e("服务端开始 start");
        if (this.mConnectThread != null) {
            this.mConnectThread.cancel();
            this.mConnectThread = null;
        }

        if (this.mConnectedThread != null) {
            this.mConnectedThread.cancel();
            this.mConnectedThread = null;
        }

        if (this.mAcceptThread == null) {
            this.mAcceptThread = new BluetoothService.AcceptThread();
            this.mAcceptThread.start();
        }

        this.setState(1);
    }

    /**
     * 进行设备连接
     *
     * @param device
     */
    public synchronized void connect(BluetoothDevice device){
        LogUtils.e("正在连接设备： " + device.getName() + "  MAC:" + device.getAddress());
        if (this.mState == 2 && this.mConnectThread != null) {
            this.mConnectThread.cancel();
            this.mConnectThread = null;
        }

        if (this.mConnectedThread != null) {
            this.mConnectedThread.cancel();
            this.mConnectedThread = null;
        }

        this.mConnectThread = new BluetoothService.ConnectThread(device);
        this.mConnectThread.start();
        this.setState(2);
    }

    public synchronized void stop() {
        LogUtils.e("BluetoothService  stop");
        this.setState(0);
        if (this.mConnectThread != null) {
            this.mConnectThread.cancel();
            this.mConnectThread = null;
        }

        if (this.mConnectedThread != null) {
            this.mConnectedThread.cancel();
            this.mConnectedThread = null;
        }

        if (this.mAcceptThread != null) {
            this.mAcceptThread.cancel();
            this.mAcceptThread = null;
        }

    }

    public OutputStream getOutputStream() {
        BluetoothService.ConnectedThread r;
        synchronized (this) {
            if (this.mState != 3) {
                return null;
            }

            r = this.mConnectedThread;
        }

        return r.getOutputStream();
    }

    public void write(byte[] out) {
        BluetoothService.ConnectedThread r;
        synchronized (this) {
            if (this.mState != 3) {
                return;
            }

            r = this.mConnectedThread;
        }

        r.write(out);
    }

    private void connectionFailed() {
        this.setState(1);
        Message msg = this.mHandler.obtainMessage(6);
        this.mHandler.sendMessage(msg);
    }

    private void connectionLost() {
        Message msg = this.mHandler.obtainMessage(5);
        this.mHandler.sendMessage(msg);
    }

    /**
     * 服务端角色连接
     */
    private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread() {
            BluetoothServerSocket tmp = null;

            try {
                tmp = BluetoothService.this.mAdapter.listenUsingRfcommWithServiceRecord("BTPrinter", BluetoothService.MY_UUID);
            } catch (IOException var4) {
                LogUtils.e("listenUsingRfcommWithServiceRecord 启动失败 " + var4.getMessage());
            }

            this.mmServerSocket = tmp;
        }

        public void run() {
            LogUtils.e("服务端代码启动");
            this.setName("AcceptThread");
            BluetoothSocket socket = null;

            while (BluetoothService.this.mState != 3) {
                LogUtils.e("AcceptThread线程运行  正在运行......");

                try {
                    socket = this.mmServerSocket.accept();
                } catch (IOException var6) {
                    LogUtils.e("  接受失败：" + var6.getMessage());
                    break;
                }

                if (socket != null) {
                    synchronized (BluetoothService.this) {
                        switch (BluetoothService.this.mState) {
                            case 0:
                            case 3:
                                try {
                                    socket.close();
                                    LogUtils.e("服务端的socket关闭");
                                } catch (IOException var4) {
                                    LogUtils.e("BluetoothService Could not close unwanted socket" + var4.getMessage());

                                }
                                break;
                            case 1:
                            case 2:
                                BluetoothService.this.connected(socket);
                        }
                    }
                }
            }

            LogUtils.e("服务端 mAcceptThread  线程运行结束");
        }

        public void cancel() {
            LogUtils.e("BluetoothService  cancel " + this);

            try {
                this.mmServerSocket.close();
            } catch (IOException var2) {
                LogUtils.e("BluetoothService  close() of server failed" + var2.getMessage());
            }

        }
    }

    /**
     * 以客户端的身份进行连接
     */
    private class ConnectThread extends Thread {
        private BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            this.mmDevice = device;
        }

        public void run() {
            this.setName("ConnectThread");
            LogUtils.e("蓝牙搜索停止  创建soclet对象进行连接");
            BluetoothService.this.mAdapter.cancelDiscovery();
            BluetoothSocket tmp = null;
            try {
                tmp = (BluetoothSocket) mmDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(mmDevice, 1);
                mmSocket = tmp;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                LogUtils.e("创建客户端连接对象出错  failed" + e.getMessage());
                BluetoothService.this.connectionFailed();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            try {
                LogUtils.e("mmSocket.isConnected():" + mmSocket.isConnected());
                this.mmSocket.connect();

            } catch (IOException var5) {
//                mHandler.sendEmptyMessage(MESSAGE_UNABLE_CONNECT);
                LogUtils.e("mmSocket.connect() 连接错误：" + var5.getMessage());
                BluetoothService.this.connectionFailed();
                try {
                    this.mmSocket.close();
                    LogUtils.e("客户端角连接失败");
                } catch (IOException var3) {
                    LogUtils.e("连接错误时关闭BluetoothSocket异常：" + var3.getMessage());
                }
                return;
            }
            synchronized (BluetoothService.this) {
                BluetoothService.this.mConnectThread = null;
                LogUtils.e("ConnectThread 线程释放");
            }

            BluetoothService.this.connected(this.mmSocket);
        }

        public void cancel() {
            try {
                if (this.mmSocket != null) {
                    this.mmSocket.close();
                }
            } catch (IOException var2) {
                LogUtils.e("BluetoothService  close() of connect socket failed" + var2.getMessage());
            }

        }
    }

    public synchronized void connected(BluetoothSocket socket) {
        LogUtils.e("创建服务端");
        if (this.mConnectThread != null) {
            this.mConnectThread.cancel();
            this.mConnectThread = null;
        }

        if (this.mConnectedThread != null) {
            this.mConnectedThread.cancel();
            this.mConnectedThread = null;
        }

        if (this.mAcceptThread != null) {
            this.mAcceptThread.cancel();
            this.mAcceptThread = null;
        }

        this.mConnectedThread = new BluetoothService.ConnectedThread(socket);
        this.mConnectedThread.start();
//        Message msg = this.mHandler.obtainMessage(4);
//        this.mHandler.sendMessage(msg);
        this.setState(3);
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            LogUtils.e("BluetoothService  create ConnectedThread");
            this.mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException var6) {
                LogUtils.e("BluetoothService  temp sockets not created" + var6.getMessage());
            }

            this.mmInStream = tmpIn;
            this.mmOutStream = tmpOut;
        }

        public void run() {
            LogUtils.e("ConnectedThread线程运行  正在运行......");

            try {
                while (true) {
                    byte[] e = new byte[256];
                    int bytes = this.mmInStream.read(e);
                    if (bytes <= 0) {
                        LogUtils.e("BluetoothService disconnected");
                        BluetoothService.this.connectionLost();
                        if (BluetoothService.this.mState != 0) {
                            LogUtils.e("BluetoothService disconnected");
                            BluetoothService.this.start();
                        }
                        break;
                    }

                    BluetoothService.this.mHandler.obtainMessage(2, bytes, -1, e).sendToTarget();
                }
            } catch (IOException var3) {
                LogUtils.e("BluetoothService disconnected" + var3.getMessage());
                BluetoothService.this.connectionLost();
                if (BluetoothService.this.mState != 0) {
                    BluetoothService.this.start();
                }
            }

        }

        public void write(byte[] buffer) {
            try {
                this.mmOutStream.write(buffer);
                BluetoothService.this.mHandler.obtainMessage(3, -1, -1, buffer).sendToTarget();
            } catch (IOException var3) {
                LogUtils.e("BluetoothService  Exception during write" + var3.getMessage());
            }

        }

        public OutputStream getOutputStream() {
            return this.mmOutStream;
        }

        public void cancel() {
            try {
                if (this.mmSocket!=null) {
                    this.mmSocket.close();
                }
            } catch (IOException var2) {
                LogUtils.e("BluetoothService  close() of connect socket failed" + var2.getMessage());
            }

        }
    }
}
